#---------------------------------------------------------
### <Script>
### <Author>Keith Hill</Author>
### <Description>
### This script generates the about_Pscx.help.txt file
### </Description>
### </Script>
#---------------------------------------------------------
param([string]$outputDir = $(throw "You must specify the output path to emit the generated file"))

function WrapText($width = 74, $indent = 8) {

	begin {
		$indent = " " * $indent
		$whitespace = "`t`r`n ".ToCharArray()
		[Text.StringBuilder]$output = $indent
		$currentLineWidth = 0
	}

	process {
		if (!$_) {
			return
		}
		
		$words = $_.Split($whitespace, [StringSplitOptions]::RemoveEmptyEntries)
		
		$index = 0
		$count = 0
		
		while(($index + $count) -lt $words.Length) {
		
			while($currentLineWidth -le $width) {
				$w = $words[$index + $count].Length + 1;
				
				if(($currentLineWidth + $w) -gt $width) {
					break
				}
				
				$currentLineWidth += $w
				$count++
			}
			
			if($count -gt 0) {
				$words[$index..($index + $count - 1)] |% {
					$output.Append($_)  | out-null
					$output.Append(' ') | out-null
				}
				
				$output.AppendLine() | out-null
				$output.Append($indent) | out-null
			}
			else {
				$word = $words[$index]
				$line = $null;
				
				do {
					if($word.Length -gt $width) {
						$line = $word.Substring(0, $width)
						$word = $word.Substring($width)
					}
					else {
						$line = $word;
						$word = $null;
					}
					
					$output.AppendLine($indent + $line) | out-null
				} while($word)
				
				$count++
			}
		
			$index += $count

			$count = 0
			$currentLineWidth = 0
		}
	}

	end {
		$output.ToString()
	}
}

function WriteLine {
	"" | OutAboutHelpFile
}

filter OutAboutHelpFile {
	$_ | Out-File $AboutPscxHelpPath -Encoding Utf8 -Append
}

#---------------------------------------------------------
# Script main
#---------------------------------------------------------
$ScriptPath = $MyInvocation.MyCommand.Path
$ScriptDir = Split-Path $ScriptPath -parent
$ModuleDir = "$ScriptDir\..\..\PscxSnapin\bin\Release"      
$PscxModule = Join-Path $ModuleDir "Pscx.dll"      

$outputDir   = Resolve-Path $outputDir
$templateDir = Split-Path $outputDir -parent
$providerHelpPath = Split-Path $outputDir -parent

$AboutPscxHelpPath = (join-path $outputDir about_Pscx.help.txt) 
$MergedHelpPath    = (join-path $outputDir MergedHelp.xml)

Import-Module $PscxModule
$PscxSnapin = Get-Module Pscx

#---------------------------------------------------------
# Process the Profile dir to extract filter/function/script help
#---------------------------------------------------------
$scriptDir = Split-Path $MyInvocation.InvocationName -parent
$scriptHelpDir = Join-Path $outputDir Scripts
if (!(Test-Path $scriptHelpDir)) {
	New-Item $scriptHelpDir -type Directory > $null
}
& "$scriptDir\ExtractScriptHelp.ps1" "$scriptDir\..\..\PscxSnapin\Profile\*.ps1" $scriptHelpDir
& "$scriptDir\ExtractScriptHelp.ps1" "$scriptDir\..\..\PscxSnapin\Scripts\*.ps1" $scriptHelpDir

$filters = $null
$functions = $null
$scripts = @()
foreach ($file in (Get-ChildItem $scriptHelpDir\*.xml)) {
	$xml = [xml](get-content $file)
	$filters += $xml.SelectNodes('//Filter')
	$functions += $xml.SelectNodes('//Function')
	if ($xml.SelectSingleNode('//Script')) {
		$scripts += $xml
	}
}
$filters   = $filters | sort name
$functions = $functions | sort name
$scripts   = $scripts | sort @{e={$_.ScriptFile.path}}

#---------------------------------------------------------
# Insert Header template
#---------------------------------------------------------
New-Item $AboutPscxHelpPath -Type File -Force > $null
Get-Content (join-path $templateDir about_Pscx_header.txt) |
	% { $_ -replace '<VERSION_NUMBER>', $PscxSnapin.Version } | OutAboutHelpFile
	
#---------------------------------------------------------
# Process Cmdlets
#---------------------------------------------------------
WriteLine
"CMDLETS" | OutAboutHelpFile
"    To see what cmdlets are provided by PSCX, execute the alias `"gcmpscx`" at" | OutAboutHelpFile
"    the PowerShell prompt.  The current PSCX cmdlets are listed below:" | OutAboutHelpFile
WriteLine
$MergedXml = [Xml](Get-Content $MergedHelpPath)
$MergedXml.Cmdlets.Cmdlet | Sort Noun, Verb | % {
	"    $($_.Verb)-$($_.Noun)"
	$_.DetailedDescription.Trim() | WrapText
} | OutAboutHelpFile

#---------------------------------------------------------
# Process Providers
#---------------------------------------------------------
WriteLine
"PROVIDERS" | OutAboutHelpFile
gci $providerHelpPath\Provider*.xml | ? {$_.Name -notmatch 'Provider_template'} | Sort Name  | % {
	$provider = [xml](Get-Content $_)
	"    $($provider.providerHelp.Name.Trim())"
	$provider.providerHelp.Synopsis.Trim() | WrapText
} | OutAboutHelpFile

#---------------------------------------------------------
# Process Filters
#---------------------------------------------------------
"FILTERS" | OutAboutHelpFile
foreach ($filter in $filters) {
	$aliases = Get-Alias | ?{$_.Definition -match "^$($filter.name)`$"} | sort name | %{$_.name}
	if ($aliases) {
		$OFS = ', '
		"    $($filter.name) ($aliases)" | OutAboutHelpFile
	}
	else {
		"    $($filter.name)" | OutAboutHelpFile
	}
	$filter.Description.Trim() | WrapText | OutAboutHelpFile
	if ($filter.Usage) {
		"        Usage:" | OutAboutHelpFile
		$filter.Usage.Trim() | Split-String -separator "`n" | %{"            $_"} | OutAboutHelpFile
	}
	WriteLine
}

#---------------------------------------------------------
# Process Functions
#---------------------------------------------------------
"FUNCTIONS" | OutAboutHelpFile
foreach ($function in $functions) {
	$aliases = Get-Alias | ?{$_.Definition -match "^$($function.name)`$"} | sort name | %{$_.name}
	if ($aliases) {
		$OFS = ', '
		"    $($function.name) ($aliases)" | OutAboutHelpFile
	}
	else {
		"    $($function.name)" | OutAboutHelpFile
	}
	$function.Description.Trim() | WrapText | OutAboutHelpFile
	if ($function.Usage) {
		"        Usage:" | OutAboutHelpFile
		$function.Usage.Trim() | Split-String -separator "`n" | %{"            $_"} | OutAboutHelpFile
		WriteLine
	}
}

#---------------------------------------------------------
# Process Scripts
#---------------------------------------------------------
"SCRIPTS" | OutAboutHelpFile
# $pscxDir = Split-Path $PscxSnapin.ModuleName -parent
# $scripts = gci $pscxDir\Scripts\*.ps1 | Sort Name | %{$_.BaseName}
foreach ($script in $scripts) {
	$scriptName = [IO.Path]::GetFilenameWithoutExtension($script.ScriptFile.path)
	$aliases = Get-Alias | ?{$_.Definition -match "^$scriptName`$"} | sort name | %{$_.name}
	if ($aliases) {
		$OFS = ', '
		"    $scriptName ($aliases)" | OutAboutHelpFile
	}
	else {
		"    $scriptName" | OutAboutHelpFile
	}
	$script.ScriptFile.Script.Description.Trim() | WrapText | OutAboutHelpFile
	if ($script.ScriptFile.Script.Usage) {
		"        Usage:" | OutAboutHelpFile
		$script.ScriptFile.Script.Usage.Trim() | Split-String -separator "`n" | %{"            $_"} | OutAboutHelpFile
		WriteLine
	}	
}

#---------------------------------------------------------
# Process Aliases
#---------------------------------------------------------
"PROFILE DEFINED ALIASES" | OutAboutHelpFile
"    To see what aliases get created by PSCX, execute the alias `"galpscx`" at" | OutAboutHelpFile
"    the PowerShell prompt.  The current PSCX defined aliases are listed below:" | OutAboutHelpFile
WriteLine
$pscxAliases = Get-Alias | Where {$_.Description -match "^PSCX" -or $_.Name -match "Pscx|__pscx"} | Sort Name
$longestAlias = ($pscxAliases | %{$_.Name.Length} | Measure-object -max).Maximum
foreach ($alias in $pscxAliases) {
	Write-Host "Processing $alias"
	$len = $alias.Name.Length
	$diff = $longestAlias - $len
	"    $($alias.Name)" + " " * $diff + 
		" : alias for $($alias.Definition) $(get-command $alias.Definition | %{$_.CommandType.ToString().ToLower()})" | 
		OutAboutHelpFile
}
WriteLine

#---------------------------------------------------------
# Append footer template
#---------------------------------------------------------
Get-Content (join-path $templateDir about_Pscx_footer.txt) | OutAboutHelpFile
